\documentclass[12pt,a4paper]{article}% 文档格式
\usepackage{listings}
\usepackage{ctex,hyperref}% 输出汉字
\usepackage{times}% 英文使用Times New Roman
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{\fontsize{18pt}{27pt}\selectfont% 小四字号，1.5倍行距
	{\heiti% 黑体 
		电子宠物大作业实验报告}}% 题目
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\author{\fontsize{12pt}{18pt}\selectfont% 小四字号，1.5倍行距
	{\fangsong% 仿宋
		\underline{赵俊宇~~PB24061271}}\\% 标题栏脚注
	\fontsize{10.5pt}{15.75pt}\selectfont% 五号字号，1.5倍行距
	{\fangsong% 仿宋
		(中国科学技术大学~~~信息科学技术学院~~~2024级本科3班)}}% 作者单位，“~”表示空格
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\date{}% 日期（这里避免生成日期）
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{amsmath,amsfonts,amssymb}% 为公式输入创造条件的宏包
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{graphicx}% 图片插入宏包
\usepackage{subfig}% 并排子图
\usepackage{subcaption}
\usepackage{float}% 浮动环境，用于调整图片位置
\usepackage[export]{adjustbox}% 防止过宽的图片
\usepackage{multirow}
\usepackage[table,xcdraw]{xcolor}
\usepackage{colortbl}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{bibentry}
\usepackage{natbib}% 以上2个为参考文献宏包
\usepackage{natbib}
\setcitestyle{numbers,square}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{abstract}% 两栏文档，一栏摘要及关键字宏包
\renewcommand{\abstracttextfont}{\fangsong}% 摘要内容字体为仿宋
\renewcommand{\abstractname}{\textbf{摘\quad 要}}% 更改摘要二字的样式
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{xcolor}% 字体颜色宏包
\newcommand{\red}[1]{\textcolor[rgb]{1.00,0.00,0.00}{#1}}
\newcommand{\blue}[1]{\textcolor[rgb]{0.00,0.00,1.00}{#1}}
\newcommand{\green}[1]{\textcolor[rgb]{0.00,1.00,0.00}{#1}}
\newcommand{\darkblue}[1]
{\textcolor[rgb]{0.00,0.00,0.50}{#1}}
\newcommand{\darkgreen}[1]
{\textcolor[rgb]{0.00,0.37,0.00}{#1}}
\newcommand{\darkred}[1]{\textcolor[rgb]{0.60,0.00,0.00}{#1}}
\newcommand{\brown}[1]{\textcolor[rgb]{0.50,0.30,0.00}{#1}}
\newcommand{\purple}[1]{\textcolor[rgb]{0.50,0.00,0.50}{#1}}% 为使用方便而编辑的新指令
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{url}% 超链接
\usepackage{bm}% 加粗部分公式
\usepackage{multirow}
\usepackage{booktabs}
\usepackage{epstopdf}
\usepackage{epsfig}
\usepackage{longtable}% 长表格
\usepackage{supertabular}% 跨页表格
\usepackage{algorithm}
\usepackage{algorithmic}
\usepackage{changepage}% 换页
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{enumerate}% 短编号
\usepackage{caption}% 设置标题
\captionsetup[figure]{name=\fontsize{10pt}{15pt}\selectfont Figure}% 设置图片编号头
\captionsetup[table]{name=\fontsize{10pt}{15pt}\selectfont Table}% 设置表格编号头
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{indentfirst}% 中文首行缩进
\usepackage[left=2.50cm,right=2.50cm,top=2.80cm,bottom=2.50cm]{geometry}% 页边距设置
\renewcommand{\baselinestretch}{1.5}% 定义行间距（1.5）
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{fancyhdr} %设置全文页眉、页脚的格式

\pagestyle{fancy}
\hypersetup{colorlinks=true,linkcolor=black}% 去除引用红框，改变颜色
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\lstset{
  basicstyle=\ttfamily\small,    % 等宽字体
  numbers=left,                   % 显示行号
  numberstyle=\tiny\color{gray},  % 行号样式
  frame=single,                   % 边框样式
  breaklines=true,                % 自动换行
  keywordstyle=\color{blue},      % 关键字颜色
  commentstyle=\color{green!40!black}, % 注释颜色
  stringstyle=\color{red}         % 字符串颜色
}

\begin{document}
\graphicspath{{E:/download}}
\begin{figure}[t]
	\includegraphics[width=0.4\textwidth]{7-1401291J307.png}
\end{figure}
\maketitle
\begin{abstract}
    电子宠物,是一个曾经风靡一时,现在却销声匿迹的低端消费电子产品.在二十一世纪初的国内,受国外流行文化影响,电子宠物从曾经是每个孩子上学出行路上必备的物品之一.定时喂养,照顾宠物,也成为了孩子们之间的话题.
    
    通过以MCU简单任务调度为核心的代码,设计有关电子宠物的各项功能,实现了具备定时安抚、心情控制、表情控制、环境反馈等功能的电子宠物.

    该作业用到的模块有LCD,温湿度传感器,超声波传感器,矩阵键盘等.
\end{abstract}
	\begin{adjustwidth}{1.06cm}{1.06cm}
		\fontsize{10.5pt}{15.75pt}\selectfont{\heiti{关键词：}\fangsong{电子宠物；模块化；多任务}}\\
	\end{adjustwidth}
\newpage
\tableofcontents
\newpage
\section{总体设计}
该程序采用自顶向下设计,核心代码是MCU的简单任务调度代码,即:\textbf{通过计数器中断,规定每个任务的执行时间,按时间轮次执行任务.}
这种方式听起来简单,但是实际操作时,有些任务需要全程执行,有些任务在其他任务执行时不能被执行,也就是说,这些任务有不同的优先级,需要不同的控制方法.

核心代码如下:
\begin{lstlisting}[language=C]
    while (1) 
    {
		for (counter=0;counter<MAX_TASKS;counter++)
		{
			if (runtask[counter].ticks<=0)
			{
				LCD_Write_Char(1,14,'0'+keyno/10);
				LCD_Write_Char(1,15,'0'+keyno%10);
				runtask[counter].ticks=ticks[counter];
				runtask[counter].ftask();
			}
			
		}
		for(counter=0;counter<100;counter++) ;
    }

\end{lstlisting}

通过这一代码,我们可以按轮次执行任务,现在,我们来看看我们要实现的功能都有什么,以及它们的优先级都有多高:

\begin{enumerate}
    \item 死亡后重新开始的代码 优先级:最高
    \item 能控制各函数依次进行的代码 优先级:最高
    \item 能打断各模块的定时安抚函数 优先级:较高
    \item 阻止其他函数运行的强制等待函数 优先级:较高
    \item 显示环境温度以确定心情值函数 优先级:较低
    \item 显示用户距离以确定心情值函数 优先级:较低
    \item 显示宠物心情函数 优先级:较低
    \item 其他辅助功能 优先级:较低
\end{enumerate}
\begin{figure}[h]
	\centering
	\includegraphics[width=0.8\textwidth]{11.png}
	\caption{功能一览图}
\end{figure}

\section{功能介绍}

\subsection{待机模式}
待机模式分为两种,一种是开机待机,此时后台不会执行任何中断函数;另一种是主动待机,由用户选择开启,仍然需要用户定时安抚.
我设计了一种共用动画,即"Waiting..."逐字符循环蹦出.

此时后台执行的函数只有键盘扫描,\textbf{当键盘扫描到不同字符,执行清屏函数,开始执行字符对应的功能.}

\subsubsection{开机待机}
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{79D3036F8AD474ADFFB8CC9F7CB2D802.jpg}
    \caption{开机待机页面动画的一帧}
\end{figure}
\pagebreak

\subsubsection{主动待机}
    按钮00可以呼出主动待机动画.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{E657D673DA7100AAE8DA582CA8C84435.jpg}
    \caption{主动待机页面}
\end{figure}
\subsection{表情随心情的变化}
我设置了四种心情,每种心情设计了三个表情切换,按钮12~15对应愤怒、开心、惊讶、冷漠四种心情.
分别有:
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{QQ20250503-203552.png}
    \caption{动画表情}
\end{figure}

不仅如此,当太远、太热、需要安抚或安抚之后,表情会发生变化,例如:
\pagebreak
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{91E8AEFD42FE876BFA13FF10A1E0969B.jpg}
    \caption{环境不合适会改变表情}
\end{figure}

用户自己设置和后台程序改变两种方式共同作用,形成了电子宠物丰富的表情系统.
\subsection{环境感知}
通过温湿度传感器和超声波传感器,我们赋予电子宠物感知外界并做出反馈的能力.
\subsubsection{温湿度传感器}
我设置的适宜室温阈值为25摄氏度,按键08呼出此界面,并激活电子宠物温湿度感知,当温适度传感器检测到室温大于25度时,
电子宠物心情值会减一,并将表情自动设置为震惊档.但是温度合适时,心情就会加回去,并将表情设置为开心档.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{E49E50D5A18FC177E326E654796CFC5C.jpg}
    \caption{太热时的反应}
\end{figure}
\pagebreak
\subsubsection{超声波传感器}
通过超声波传感器测量距离,按键09呼出此界面,并显示用户与电子宠物间的距离.和温湿度传感器一致,当距离过远时,
电子宠物心情值会减一,并将表情设置为愤怒档.但是距离合适时,心情就会加回去,并将表情设置为开心档,再重置定时安抚时间.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{0380FFEE32410C5B91A0B837B1EFC56A.jpg}
    \caption{距离合适时的反应}
\end{figure}

\subsection{定时安抚}
电子宠物会在后台不断记录用户与宠物的距离,当60秒内距离都较远时,定时安抚函数会打断所有任务并要求用户安抚,
此时代码层面上,中断关闭,表情切换到愤怒档,需要用户主动安抚.在安抚后,会跳转回原来进行的任务并将表情切换为开心档.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{1BAECA20AA4DC2E40DB8A4B8132CC72A.jpg}
    \caption{打断后的强制安抚界面}
\end{figure}

\subsection{心情系统}
上面提到的心情类变化通过一个结构体整合起来,统称为心情系统.通过按键10呼出心情界面查看心情.和市面上的电子宠物一样,心情太低会死亡,这也过渡到我们要介绍的死亡系统.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{D93DCB73F2822D301536E189467D6D20.jpg}
    \caption{心情界面}
\end{figure}
\subsection{死亡系统}
当心情归零时,电子宠物会死亡并强制进入死亡界面,用户需要按下任意键复活.复活后心情会补满并进入00主动待机界面.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{0CA05B911806073374D7B4866FB70127.jpg}
    \caption{死亡界面}
\end{figure}

\subsection{发声系统}
借助蜂鸣器,我们可以实现发声系统,主要是在要求安抚时发动提示音.此外,按键`3'可以呼出演奏一段音乐.

\subsection{游戏系统}
按下`4'呼出游戏系统,通过摇杆操纵小人越过障碍物,成功则增加一个心情,失败不增加.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{869BA3C6E6098B87B6A79BBD75F980E3.jpg}
    \caption{游戏界面}
\end{figure}
\subsection{存活时间统计}
按键01进入存活时间统计界面,电子宠物会在后台记录存活时间并显示出来.待机模式不会计入总时长,同时,电子宠物死亡后复活会重新计算时长.
\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{3874CE7E4BF40520601470AE70801CEA.jpg}
    \caption{存活计时界面}
\end{figure}

\subsection{总结}
通过如下规划任务,我们实现这些系统间的协调.
\begin{lstlisting}[language=C]
    int ticks[MAX_TASKS]={150,4000,200,1000,1000,1000,150,120};
    OSTASK runtask[MAX_TASKS]={
	{segctrl,150},{face,4000},{weather_seg8,200},{comfortseg,1000},
	{waiting,1000},{showwaiting,1000},{showmood,150},{LiveOrDie,120}
	};
\end{lstlisting}
\section{代码实现}
\subsection{实现待机时的动画并且不执行中断}
看见这个问题,我们的第一反应或许是直接cli()关闭中断,但是,如果直接关闭,矩阵键盘在后台就不会扫描,换句话说,程序会直接卡死在等待界面.\textbf{那么,我们就需要另一种思路,实现
在开机时不执行其他任务,但是按下键盘时可以启动.}

针对这个问题,我的解决方法是单独分配一个变量记录状态,并针对不同优先级设置不同的应对策略.我们来看以下代码:
\begin{lstlisting}[language=C]
    void waiting(void){
	if (keyno!=16)
	{
		return (void)0;
	}
	LCD_Write_String(1,0,Totalclear_down);
	unsigned char i;
	for (i=0;i<10;i++)
	{
		LCD_Write_Char(1,i,wait[i]);
		_delay_ms(125);
	}
}
\end{lstlisting}

在开始时我们把键盘值设置为不可能值——16,使得其他函数在开始时通过if(keyno!=对应值)并结束.
同时,我们再分配一个变量,设置为1,即:
\begin{lstlisting}[language=C]
    unsigned char target_start=1;
\end{lstlisting}

在后台函数执行时,若此变量为1,就继续通过if语句结束.直到我们按下任意按键,改变keyno值并进入对应函数,当keyno值匹配时,函数就能顺利进行,改变targetstart值,实现清屏.

\textbf{对于不同优先级函数,处理的策略并不相同},低优先级时:
\begin{lstlisting}[language=C]
        if (keyno!=8)
	{
		return (void)0;
	}
	if(target_start)
       {
		target_start--;
		lcd_clear();
		
	}
\end{lstlisting}
低优先级函数只有呼出时才进行,在后台并不执行,所以首先判断keyno值,再判断需不需要清屏.

高优先级时:
\begin{lstlisting}[language=C]
        if (target_start&&(keyno>11&&keyno<16))
	{
		target_start--;
		lcd_clear();
		
	}
	else if(keyno ==16){
		return (void)0;
	}
\end{lstlisting}
在开机时,keyno为16,高优先级函数结束,但是当按下对应按键时,执行清屏并退出待机模式.

\subsection{实现进行其他任务时打断并要求安抚}
\textbf{安抚时间设定在60秒,毫无疑问是超出计时器范围的,而且还需要在后台靠近时,就能重置计时,那代表着需要特殊的控制方法.首先,先把安抚函数设置成
每秒执行一次,实现后台定时启动.}针对60秒,我们这么设计:
\begin{lstlisting}[language=C]
    static char calling=FEEDTIME;
    cli();
	distance=HCSR04_Run();
	sei();
	if (distance<=FEEDDISTANCE&&keyno!=9)
	{
		calling=FEEDTIME;
		return (void)0;
	}
	else if (distance<=FEEDDISTANCE&&keyno==9)
	{
		calling=FEEDTIME;
	}
	calling--;
\end{lstlisting}
当我们不需要按下09界面显示距离时,就只需要判断距离再结束;需要显示时,再做处理.

每当函数执行时,关闭中断,计算距离,当距离小于预定值时,符合要求,将calling值重新设置为预定值;但是,当距离大于预定值时,calling值减一.
如此重复在后台执行,当calling归零时,就通过if判断进入下一步处理.

这样,我们就实现了强制安抚功能.

\subsection{实现安抚后跳转回原任务}
单看前面要实现的功能,keyno+targetstart两个变量的处理并不是最优解,甚至还有着不小的优化空间,但是结合跳转回原任务的功能,这一处理就很有必要了.

如果缺少前一个变量,在安抚函数后,就会卡死在安抚界面直到用户手动设置;如果缺少后一个变量,就不能实现完美的待机效果.

因此,借由前面提到的处理方法,我们成功实现了跳转回原任务的功能.

\subsection{心情归零引起的死亡}
我们先来看整个函数的核心代码.
\begin{lstlisting}[language=c]
    void LiveOrDie(void){
	unsigned char sum_mood=mood.comfort+mood.tmp;
	if (sum_mood==0)
	{
		_delay_ms(1000);
		keyno=16;
		lastkey=16;
		target_start=1;
		lcd_clear();
		LCD_Write_String(0,0," X_X   GAME OVER");
		LCD_Write_String(1,0,"Press To Restart");
		while(keyno==16) {
			segctrl();
			_delay_ms(100);
		}
	}
}
\end{lstlisting}

通过设计函数,我们可以定时检测宠物心情,在检测心情归零后,执行这一函数.同时,矩阵键盘在后台不断扫描,按下任意键,keyno改变,从而结束while循环,实现复活.

\subsection{矩阵键盘的拆分连接与去抖处理}
在课上,我们的矩阵键盘八个IO都连接了PC0-7,这使得对DDR等一系列变量的修改相对简单.但随着我们使用的元器件的增加,我们不得不将其拆开连接,改进后的代码如下:
\begin{lstlisting}[language=C]
	void segctrl(void){
	unsigned char i,j,getkey;
	DDRC |=0x0f;
	DDRB &=~0xf0;
	PORTB |=0xf0;
	PORTC |=0x0f;
	
	for (i=0;i<4;i++)
	{
		
		PORTC &=~(1<<(i));
		for (j=0;j<4;j++)
		{
			if (i!=j)
			{
				PORTC |=(1<<j);
			}
		}
		_delay_us(2);
		getkey =(PINB & 0xf0)>>4;
		switch(getkey){
			case 0x0e:keyno =4*i;break;
			case 0x0d:keyno =4*i+1;break;
			case 0x0b:keyno =4*i+2;break;
			case 0x07:keyno =4*i+3;break;
		}
		
	}
}
\end{lstlisting}

通过位运算,我们改变PC0-3和PB4-7并确保同时不改变其他值.相比于单一连接时的直接赋值,需要一个循环实现,相比较而言更加麻烦.

另外,通过增加delay,我们实现键盘的防抖,使机械信号更加稳定.

\subsection{蜂鸣器演奏}
模仿市面上的电子宠物,我们实现蜂鸣器演奏,代码如下:
\begin{lstlisting}[language=C]
	while(music[i]){
			freq=letter[music[i]];
			if (freq>0)
			{
				ICR1 =F_CPU/2/8/freq;
				OCR1A=ICR1/2;
			}
			i++;
			_delay_ms(250);
		}
		_delay_ms(1000);
\end{lstlisting}

通过这段代码,我们可以实现不同音调的发声,并利用i的增加切换音符.其中,对ICR1和OCR1A的改变变相改变了频率,是必要的.
\section{克服的难题}

\subsection{LCD频闪问题}
设置不当,LCD显示内容会进行频闪,十分影响观感.分析原因,主要是因为显示函数运行的时间较长,每个周期清屏就会导致频闪.
针对这个问题,解决方案主要有两种,一种是缩短运行时长,另一种是只在切换函数时清屏.

第一种方法毫无疑问在函数比较庞大时较难实现,那就把目光放到第二种方法.

我们引入变量lastkey,记录上一次的键盘值.当两次键盘值匹配时,说明没有切换界面,就不需要反复清屏,只需要显示变化的部分.

\subsection{长时间不安抚后卡死问题}
在强制安抚界面,后台是在持续计数的,可是界面被强制固定在此,那么,在较长时间后,就会出现计数器溢出卡死问题.
针对这个问题,我们需要特殊处理,让此强制界面弹出时,后台函数获得优化.方法有二,一种是再引入一个全新变量记录这一状态,另一种是关闭中断,只通过循环不断探测距离.
当距离达到合适要求再结束循环.

我们采取第二种做法,直接关闭中断,原因是,为了保证这一界面的强制性,此时不可以让其他函数工作也不能在后台计入存活时长.所以用这种方法处理.

\subsection{delay函数参数必须使用常量问题}
delay函数的参数必须使用常量,但我们在演奏音乐时需要使用while循环并增加变量值以改变,因此简单将数组值作为参数会报错.
为了解决这一问题,我们将delay函数``套一层皮'':
\begin{lstlisting}[language=C]
	void soft_delay_ms(unsigned int ms) {
	while(ms--) {
		_delay_ms(1);  // 这里的1是编译时常量
	}
}
\end{lstlisting}

通过这样,我们可以将变量作为delay函数的参量.

\section{细节优化}
由于牵涉到多个系统,对细节的优化是一项比较大的工程.需要考虑各系统间的运行逻辑是否合理,以及显示细节是否处理得当.


主要问题集中在前台任务的切换部分,常有上一个任务显示的字符在此任务中没有及时得到清理而导致的显示错误.

另外,各系统间涉及到互相影响、互相改变,比如,感知系统会改变表情系统和心情系统,用户的干扰也会改变这些参数.这就需要建立合适的变量和函数间的调用关系,
这里我使用了思维导图的形式理清关系,从而逐步编写函数.
\begin{figure}[h]
	\centering
	\includegraphics[width=0.8\textwidth]{12.png}
	\caption{各模块间的关系与细节优化一览图}
\end{figure}

\subsection{前台任务切换优化}
针对任务切换时可能出现的字符残留问题,我们在界面切换逻辑中增加了动态清屏机制:仅在检测到键盘值变化(触发功能切换)时执行清屏操作,确保当前任务界面无历史残留信息.通过这一改进,有效避免了显示错误,提升了界面整洁度.

\subsection{跨模块交互逻辑设计}
各系统间存在复杂的联动关系(如环境感知影响心情值、心情值驱动表情变化),我们通过思维导图梳理变量与函数调用关系,建立了清晰的交互模型:

\textcircled{1}\textbf{环境感知模块}:温湿度 / 距离数据实时影响心情系统,触发对应的表情切换逻辑(如过热→震惊表情、过远→愤怒表情).

\textcircled{2}\textbf{定时安抚模块}:作为高优先级任务,可打断低优先级任务(如显示更新、环境检测),通过calling变量控制计时逻辑,距离合适时自动重置计时.

\textcircled{3}\textbf{状态协同机制}:利用keyno与target\_start变量标记操作状态,确保任务切换时的上下文连贯性(如安抚后跳转回原任务).

\section{反思总结}
这次大作业的代码量是平时实验课的数倍不止,在这次大作业的编写过程中,得到机会,回顾了各个元件的使用方法.

以开发板作为平台,成功搭建了一个较完整的电子宠物系统,也成功协调了各个模块之间的应用关系.
但受限于时间,该作业仍存在诸多不足之处,实现的功能尚浅,代码还有较大的优化空间.这些缺陷即是遗憾,也是我今后学习改进方向的指路标.


这门课程让我从电子设计 “小白” 逐步成长,不仅掌握了 MCU 编程的基础技能,更培养了分模块调试的工程思维.在报告完成之际,我满怀感恩之心,由衷感谢科大开设这门实践性极强的课程,也特别感谢李玉虎老师在遇到问题时给予的细致指导和耐心解答,在课上的生动讲解,帮助我顺利完成学习目标.
这些经历能让我运用所学,在本课程的学习与实验为本次大作业的完成提供了重要支持,这份收获与成长离不开授课老师李老师的教导与付出.

虽然本文仍有瑕疵,但这段经历让我所获颇丰,相信在此课程收获的知识与思维将使我收益良久.
\end{document}